<?php

// @formatter:off
/**
 * @file WCHolderKeyword.abs.php
 * @author Alejandro Dario Simi
 * @date $Date: 2014-06-03 03:40:32 +0000 (Tue, 03 Jun 2014) $
 *
 * $Id: WCHolderKeyword.abs.php 112 2014-06-03 03:40:32Z daemonraco@gmail.com $
 * $URL: http://wcomix.googlecode.com/svn/trunk/includes/holders/WCHolderKeyword.abs.php $
 */
// @formatter:on

/**
 * @class WCHolderKeyword
 *
 * @warning Every object called item should have two basic properties:
 *  - name
 *  - id
 */
abstract class WCHolderKeyword extends WCHolder implements WCHolderKeywordDependant {
	/**
	 * @var string This variable holds the name of the column of represented
	 * item's keyword.
	 * By default, it is 'keyword'.
	 */
	protected $_PropertiesKeywordColumn = "keyword";
	protected $_restrictedKeyword = false;
	//
	// Public methods.
	public function create($name) {
		WCErrors::I()->error(WC_HTTPERROR_INTERNAL_SERVER_ERROR, "This method can't be used directly. 'createInKeyword()' must be used.");
		return null;
	}
	/**
	 * This method allows to create a new item in the database. It also adds
	 * it to the internal list.
	 *
	 * @param string $name Name of the new item to be created.
	 * @param WCKeyword $keyword
	 * @return WCRepresentation On success returns the new object.
	 * Otherwise returns a null pointer.
	 */
	public function createInKeyword($name, $keyword) {
		//
		// Loading global pointers.
		global $wcDefaults;
		//
		// This is the default value in case the item cannot be created.
		$out = null;
		//
		// Checking that Read Only Mode is not activated.
		if(!$wcDefaults["read-only"]) {
			//
			// Checking if there's no other item with the same name.
			// Unless duplicates are allowed.
			if($this->_PropertiesDupNames || count($this->itemByNameInKeyword($name, $keyword)) == 0) {
				//
				// Creating the statement to add an item.
				// @{
				$stmt = null;
				$stmtId = __CLASS__."::".__FUNCTION__."[{$this->_PropertiesTable}]";
				if($this->_db->has($stmtId)) {
					$stmt = $this->_db->get($stmtId);
				} else {
					$query = "insert\n";
					$query .= "        into {$this->_dbprefix}{$this->_PropertiesTable} (\n";
					$query .= "                {$this->_PropertiesPrefix}{$this->_PropertiesNameColumn}, {$this->_PropertiesPrefix}{$this->_PropertiesKeywordColumn})\n";
					$query .= "        values (:name, :keyword)";

					$stmt = $this->_db->prepare($stmtId, $query);
				}
				// @}
				//
				// Inserting the new item into the database.
				$params = array(
					":name" => $name,
					":keyword" => $keyword
				);
				if($stmt->execute($params)) {
					//
					// If there were no issues creating the
					// item, it is add to the list and
					// returned.
					$out = $this->item($this->_db->lastInsertId());
				}
			}
		}
		//
		// Returning the results of the creation.
		return $out;
	}
	public function itemByKeyword($keyword) {
		//
		// Setting default value to be returned.
		$out = array();

		if(!$this->_restrictedKeyword || $this->_restrictedKeyword == $keyword) {
			foreach($this->itemIdsByKeyword($keyword) as $id) {
				$item = $this->item($id);
				if($item) {
					$out[] = $item;
				}
			}
		}

		return $out;
	}
	public function itemIdsByKeyword($keyword) {
		//
		// Setting default value to be returned.
		$out = array();

		if(!$this->_restrictedKeyword || $this->_restrictedKeyword == $keyword) {
			//
			// Preparing the statement to load items.
			// @{
			$stmt = null;
			$stmtId = __CLASS__."::".__FUNCTION__."[{$this->_PropertiesTable}]";
			if($this->_db->has($stmtId)) {
				$stmt = $this->_db->get($stmtId);
			} else {
				$query = "select  {$this->_PropertiesPrefix}id as id\n";
				$query.= "from    {$this->_dbprefix}{$this->_PropertiesTable}\n";
				$query.= "where   {$this->_PropertiesPrefix}{$this->_PropertiesKeywordColumn} = :keyword\n";
				$stmt = $this->_db->prepare($stmtId, $query);
			}
			// @}
			$params = array(
				":keyword" => $keyword
			);
			//
			// Asking for the ids.
			if($stmt->execute($params) && $stmt->rowCount() > 0) {
				//
				// Generating the list of items from database
				// results.
				foreach($stmt->fetchAll() as $row) {
					$out[] = $row["id"];
				}
			}
		}

		return $out;
	}
	public function itemByNameInKeyword($name, $keyword) {
		//
		// Setting default value to be returned.
		$out = array();

		if(!$this->_restrictedKeyword || $this->_restrictedKeyword == $keyword) {
			//
			// Generating the list of items.
			foreach($this->idsByNameInKeyword($name, $keyword) as $id) {
				$item = $this->item($id);
				if($item) {
					$out[] = $item;
				}
			}
		}
		//
		// Returning found item.
		return $out;
	}
	/**
	 * This method looks for an item by its name ignoring case.
	 *
	 * @param string $name Name of the element to retrieve.
	 * @param WCKeyword $keyword Keyword where the retrieving element belongs.
	 * @param WCRepresentation Returns a representation element. When
	 * the name doesn't match it returns false.
	 */
	public function itemByNameInKeywordCI($name, $keyword) {
		//
		// Setting default value to be returned.
		$out = array();

		if(!$this->_restrictedKeyword || $this->_restrictedKeyword == $keyword) {
			//
			// Generating the list of items.
			foreach($this->idsByNameInKeyword($name, $keyword, false) as $id) {
				$item = $this->item($id);
				if($item) {
					$out[] = $item;
				}
			}
		}
		//
		// Returning found item.
		return $out;
	}
	public function idsByNameInKeyword($name, $keyword, $caseSensitive = true) {
		//
		// Setting default value to be returned.
		$out = array();
		//
		// Preparing the statement to load items.
		// @{
		$stmt = null;
		$stmtId = __CLASS__."::".__FUNCTION__."[{$this->_PropertiesTable}".($caseSensitive ? "" : "-CI")."]";
		if($this->_db->has($stmtId)) {
			$stmt = $this->_db->get($stmtId);
		} else {
			$query = "select  {$this->_PropertiesPrefix}id as id\n";
			$query.= "from    {$this->_dbprefix}{$this->_PropertiesTable}\n";
			$query.= "where   {$this->_PropertiesPrefix}{$this->_PropertiesKeywordColumn} = :keyword\n";
			if($caseSensitive) {
				$query.= " and    {$this->_PropertiesPrefix}{$this->_PropertiesNameColumn} = :name\n";
			} else {
				$query.= " and    lower({$this->_PropertiesPrefix}{$this->_PropertiesNameColumn}) = lower(:name)\n";
			}
			$stmt = $this->_db->prepare($stmtId, $query);
		}
		// @}
		$params = array(
			":keyword" => $keyword,
			":name" => $name
		);
		//
		// Asking for the ids.
		if($stmt->execute($params) && $stmt->rowCount() > 0) {
			//
			// Generating the list of items from database
			// results.
			foreach($stmt->fetchAll() as $row) {
				$out[] = $row["id"];
			}
		}
		//
		//
		return $out;
	}
	public function restrictKeyword($keyword) {
		$this->_restrictedKeyword = $keyword;
	}
	public function unrestrictKeywords() {
		$this->_restrictedKeyword = false;
	}
	//
	// Protected methods.
}
